#include "gif.h"

#include <multimedia/image/image_pixel_map.h>
#ifdef __cplusplus
extern "C"{
#endif

static constexpr int32_t PIXEL_OFFSET = 588 * 342 + 360;

int lockPixels(JNIEnv *env, jobject jbitmap, GifInfo *info, void **pixels) {
    OhosPixelMapInfo bitmapInfo;
    if (GetImageInfo(env, jbitmap, bitmapInfo) == OHOS_IMAGE_RESULT_SUCCESS) {
        info->stride = bitmapInfo.width;
    } else {
        throwException(env, RUNTIME_EXCEPTION_BARE, "Could not get bitmap info ");
        return -2;
    }

    const int lockPixelsResult = AccessPixels(env, jbitmap, pixels);
    if (lockPixelsResult == OHOS_IMAGE_RESULT_SUCCESS) {
        return 0;
    }

    char *message;
    switch (lockPixelsResult) {
        case OHOS_IMAGE_RESULT_BAD_PARAMETER:
            message = "Lock pixels error, bad parameter";
            break;
        case OHOS_IMAGE_RESULT_JNI_EXCEPTION:
            message = "Lock pixels error, JNI exception";
            break;
        default:
            message = "Lock pixels error";
    }
    throwException(env, RUNTIME_EXCEPTION_BARE, message);
    return -2;
}

void unlockPixels(JNIEnv *env, jobject jbitmap) {
    const int unlockPixelsResult = UnAccessPixels(env, jbitmap);
    if (unlockPixelsResult == OHOS_IMAGE_RESULT_SUCCESS) {
        return;
    }
    char *message;
    switch (unlockPixelsResult) {
        case OHOS_IMAGE_RESULT_BAD_PARAMETER:
            message = "Unlock pixels error, bad parameter";
            break;
        case OHOS_IMAGE_RESULT_JNI_EXCEPTION:
            message = "Unlock pixels error, JNI exception";
            break;
        default:
            message = "Unlock pixels error";
    }
    throwException(env, RUNTIME_EXCEPTION_BARE, message);
}

JNIEXPORT jlong JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_renderFrame(JNIEnv *env, jclass handleClass, jlong gifInfo, jobject jbitmap) {
    GifInfo *info = (GifInfo *) (intptr_t) gifInfo;
    if (info == NULL)
        return -1;

    long renderStartTime = getRealTime();
    void *pixels;
    if (lockPixels(env, jbitmap, info, &pixels) != 0) {
        return 0;
    }
    DDGifSlurp(info, true, false);
    if (info->currentIndex == 0) {
        prepareCanvas((argb*)pixels, info);
    }
    const uint_fast32_t frameDuration = getBitmap((argb*)pixels, info);
    unlockPixels(env, jbitmap);
    return calculateInvalidationDelay(info, renderStartTime, frameDuration);
}

#ifdef __cplusplus
}
#endif